home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / gnuplot / contrib / campbell / gplotlib.4 < prev    next >
Encoding:
Internet Message Format  |  1992-04-27  |  40.0 KB

  1. From jdc@naucse.cse.nau.edu Thu Mar  5 09:27:04 1992
  2. Return-Path: <jdc@naucse.cse.nau.edu>
  3. Received: from naucse.cse.nau.edu by ra-next.arc.nasa.gov (NeXT-1.0 (From Sendmail 5.52)/NeXT-1.0)
  4.     id AA10634; Thu, 5 Mar 92 09:26:53 PST
  5. Received: by naucse.cse.nau.edu (5.65c/1.5-nau)
  6.     id AA21540; Thu, 5 Mar 1992 10:32:37 -0700
  7. Message-Id: <199203051732.AA21540@naucse.cse.nau.edu>
  8. From: jdc@naucse.cse.nau.edu (John Campbell)
  9. Date: Thu, 5 Mar 1992 10:32:35 MST
  10. X-Mailer: Mail User's Shell (7.2.3 5/22/91)
  11. To: woo@ra-next.arc.nasa.gov
  12. Subject: gplotlib.shr4
  13. Status: R
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 4 (of 5)."
  22. # Contents:  gsr.c
  23. # Wrapped by jdc@naucse.cse.nau.edu on Tue Feb 11 08:42:16 1992
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. if test -f 'gsr.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'gsr.c'\"
  27. else
  28. echo shar: Extracting \"'gsr.c'\" \(37808 characters\)
  29. sed "s/^X//" >'gsr.c' <<'END_OF_FILE'
  30. X#define GSR_OWNER
  31. X#include "gsr.h"
  32. X
  33. X/*-
  34. X   gnuplot Graphics Support Routines: gsr.c
  35. X
  36. X   This module provides graphics routines similar to those used to
  37. X   implement gnuplot.  These routines are based on (and require) the
  38. X   gnuplot Graphics Terminal library (gterm.c).
  39. X-*/
  40. X
  41. Xvoid plot_impulses();
  42. Xvoid plot_lines();
  43. Xvoid plot_points();
  44. Xvoid plot_dots();
  45. Xvoid edge_intersect();
  46. XBOOLEAN two_edge_intersect();
  47. X
  48. X
  49. X#define inrange(z,min,max) \
  50. X((min<max) ? ((z>=min)&&(z<=max)) : ((z>=max)&&(z<=min)) )
  51. X
  52. X/* (DFK) Watch for cancellation error near zero on axes labels */
  53. X#define SIGNIF (0.01)        /* less than one hundredth of a tic mark */
  54. X#define CheckZero(x,tic) (fabs(x) < ((tic) * SIGNIF) ? 0.0 : (x))
  55. X#define NearlyEqual(x,y,tic) (fabs((x)-(y)) < ((tic) * SIGNIF))
  56. X
  57. X/* (DFK) For some reason, the Sun386i compiler screws up with the CheckLog 
  58. X * macro, so I write it as a function on that machine.
  59. X */
  60. X#ifndef sun386
  61. X/* (DFK) Use 10^x if logscale is in effect, else x */
  62. X#define CheckLog(log, x) ((log) ? pow(10., (x)) : (x))
  63. X#else
  64. Xstatic double CheckLog(log, x)
  65. X     BOOLEAN log;
  66. X     double x;
  67. X{
  68. X  if (log)
  69. X    return(pow(10., x));
  70. X  else
  71. X    return(x);
  72. X}
  73. X#endif /* sun386 */
  74. X
  75. X
  76. Xstatic double LogScale(coord, islog, what, axis)
  77. X    double coord;            /* the value */
  78. X    BOOLEAN islog;            /* is this axis in logscale? */
  79. X    char *what;            /* what is the coord for? */
  80. X    char *axis;            /* which axis is this for ("x" or "y")? */
  81. X{
  82. X    if (islog) {
  83. X       if (coord <= 0.0) {
  84. X          char errbuf[100];        /* place to write error message */
  85. X        (void) sprintf(errbuf,"%s has %s coord of %g; must be above 0 for log scale!",
  86. X                what, axis, coord);
  87. X          (*GTterm_tbl[GTterm].text)();
  88. X          (void) fflush(GSRoutfile);
  89. X          int_error(errbuf, NO_CARET);
  90. X       } else
  91. X        return(log10(coord));
  92. X    } else {
  93. X       return(coord);
  94. X    }
  95. X    return((double)NULL); /* shut lint up */
  96. X}
  97. X
  98. X/* borders of plotting area */
  99. X/* computed once on every call to do_plot */
  100. Xstatic boundary(scaling)
  101. X    BOOLEAN scaling;        /* TRUE if terminal is doing the scaling */
  102. X{
  103. X    register struct termentry *t = >term_tbl[GTterm];
  104. X    GSRxleft = (t->h_char)*12;
  105. X    GSRxright = (scaling ? 1 : GTxsize) * (t->xmax) - (t->h_char)*2 - (t->h_tic);
  106. X    GSRybot = (t->v_char)*5/2 + 1;
  107. X    GSRytop = (scaling ? 1 : GTysize) * (t->ymax) - (t->v_char)*3/2 - 1;
  108. X}
  109. X
  110. X
  111. Xstatic double dbl_raise(x,y)
  112. Xdouble x;
  113. Xint y;
  114. X{
  115. Xregister int i;
  116. Xdouble val;
  117. X
  118. X    val = 1.0;
  119. X    for (i=0; i < abs(y); i++)
  120. X        val *= x;
  121. X    if (y < 0 ) return (1.0/val);
  122. X    return(val);
  123. X}
  124. X
  125. X
  126. Xstatic double make_tics(tmin,tmax,logscale)
  127. Xdouble tmin,tmax;
  128. XBOOLEAN logscale;
  129. X{
  130. Xregister double xr,xnorm,tics,tic,l10;
  131. X
  132. X    xr = fabs(tmin-tmax);
  133. X    
  134. X    l10 = log10(xr);
  135. X    if (logscale) {
  136. X        tic = dbl_raise(10.0,(l10 >= 0.0 ) ? (int)l10 : ((int)l10-1));
  137. X        if (tic < 1.0)
  138. X            tic = 1.0;
  139. X    } else {
  140. X        xnorm = pow(10.0,l10-(double)((l10 >= 0.0 ) ? (int)l10 : ((int)l10-1)));
  141. X        if (xnorm <= 2)
  142. X            tics = 0.2;
  143. X        else if (xnorm <= 5)
  144. X            tics = 0.5;
  145. X        else tics = 1.0;    
  146. X        tic = tics * dbl_raise(10.0,(l10 >= 0.0 ) ? (int)l10 : ((int)l10-1));
  147. X    }
  148. X    return(tic);
  149. X}
  150. X
  151. X
  152. Xgsr_init (fp, min_x, max_x, min_y, max_y, auto_x, auto_y, log_x, log_y)
  153. XFILE *fp;
  154. Xdouble min_x, max_x;
  155. Xdouble min_y, max_y;
  156. XBOOLEAN auto_x, auto_y, log_x, log_y;
  157. X/*-
  158. X   Initialize the internal variables used by the Gnuplot graphics support
  159. X   routines.  Note that this routine should be called at least once before
  160. X   any plot and at least once after changing the terminal type.
  161. X
  162. X   Parameters:
  163. X
  164. X           fp: Output file pointer.  This is stored as GSRoutfile (which is
  165. X               the same as GToutfile) and is the stream where all the 
  166. X               output for the plot is written.  If fp is different than 
  167. X               GSRoutfile then the old GSRoutfile is replaced with the
  168. X               new fp.  Note that the old fp is *not* closed, this is the
  169. X               responsibility of the caller.  If fp is NULL the old 
  170. X               GSRoutfile continues to be used.
  171. X
  172. X        min_x:  Minimum x value that you intend to plot (in your own units).
  173. X
  174. X        max_x:  Maximum x value that you intend to plot (in your own units).
  175. X
  176. X        min_y:  Minimum y value that you intend to plot (in your own units).
  177. X
  178. X        max_y:  Maximum y value that you intend to plot (in your own units).
  179. X
  180. X       auto_x:  Automatically adjust the x tics to a sensible round-off point.
  181. X
  182. X       auto_y:  Automatically adjust the y tics to a sensible round-off point.
  183. X
  184. X        log_x:  Prepare for a logarithmic scale in the x dimension.
  185. X
  186. X        log_y:  Prepare for a logarithmic scale in the y dimension.
  187. X
  188. X-*/
  189. X{
  190. Xregister struct termentry *t = >term_tbl[GTterm];
  191. Xregister int xl, yl;
  192. Xdouble xtemp, ytemp;
  193. Xstruct text_label *this_label;
  194. Xstruct arrow_def *this_arrow;
  195. XBOOLEAN scaling;
  196. X
  197. X/* Make sure a terminal has been selected. */
  198. X   if (GTterm == 0) {
  199. X      gt_init_terminal();
  200. X      if (GTterm == 0) {
  201. X        int_error ("GTterm is 0--have you defined the variable GNUTERM?");
  202. X      }
  203. X   }
  204. X
  205. X/* Take care of GSRoutfile. */
  206. X   if (fp == NULL) {
  207. X      if (GSRoutfile == NULL) {
  208. X         int_error("GSRoutfile NULL--gsr_init needs a file pointer!",NO_CARET);
  209. X      }
  210. X   }
  211. X   else {
  212. X      GSRoutfile = fp;
  213. X   }
  214. X
  215. X/* store these in variables global to this file */
  216. X/* otherwise, we have to pass them around a lot */
  217. X    GSRxmin = min_x;
  218. X    GSRxmax = max_x; 
  219. X      GSRymin = min_y;
  220. X    GSRymax = max_y;
  221. X        GSRlogx = log_x;
  222. X        GSRlogy = log_y;
  223. X
  224. X/* SETUP RANGES, SCALES AND TIC PLACES */
  225. X    GSRytic = make_tics(GSRymin,GSRymax,GSRlogy);
  226. X    
  227. X   if (auto_y) {
  228. X      if (GSRymin < GSRymax) {
  229. X         GSRymin = GSRytic * floor(GSRymin/GSRytic);       
  230. X         GSRymax = GSRytic * ceil(GSRymax/GSRytic);
  231. X      }
  232. X      else {            /* reverse axis */
  233. X         GSRymin = GSRytic * ceil(GSRymin/GSRytic);       
  234. X         GSRymax = GSRytic * floor(GSRymax/GSRytic);
  235. X       }
  236. X    }
  237. X
  238. X    GSRxtic = make_tics(GSRxmin,GSRxmax,GSRlogx);
  239. X       
  240. X    if (auto_x) {
  241. X        if (GSRxmin < GSRxmax) {
  242. X            GSRxmin = GSRxtic * floor(GSRxmin/GSRxtic);    
  243. X            GSRxmax = GSRxtic * ceil(GSRxmax/GSRxtic);
  244. X      } else {
  245. X            GSRxmin = GSRxtic * ceil(GSRxmin/GSRxtic);
  246. X            GSRxmax = GSRxtic * floor(GSRxmax/GSRxtic);    
  247. X       }
  248. X    }
  249. X
  250. X/*    This was GSRxmax == GSRxmin, but that caused an infinite loop once. */
  251. X    if (fabs(GSRxmax - GSRxmin) < ZERO)
  252. X        int_error("GSRxmin should not equal GSRxmax!",NO_CARET);
  253. X    if (fabs(GSRymax - GSRymin) < ZERO)
  254. X        int_error("GSRymin should not equal GSRymax!",NO_CARET);
  255. X
  256. X/* INITIALIZE TERMINAL */
  257. X    if (!GTterm_init) {
  258. X        (*t->init)();
  259. X        GTterm_init = TRUE;
  260. X    }
  261. X    scaling = (*t->scale)(GTxsize, GTysize);
  262. X
  263. X     /* now compute boundary for plot (GSRxleft, GSRxright, GSRytop, GSRybot) */
  264. X     boundary(scaling);
  265. X
  266. X/* SCALE FACTORS  (gsr_map_x & y will now be ready to use) */
  267. X    GSRyscale = (GSRytop - GSRybot)/(GSRymax - GSRymin);
  268. X    GSRxscale = (GSRxright - GSRxleft)/(GSRxmax - GSRxmin);
  269. X}
  270. X    
  271. Xgsr_graphics()
  272. X/*-
  273. X   Routine to call the proper terminal t->graphics() routine.  This
  274. X   should be called prior to trying to draw anything on the graphics
  275. X   terminal.
  276. X-*/
  277. X{
  278. Xregister struct termentry *t = >term_tbl[GTterm];
  279. X
  280. X    (*t->graphics)();
  281. X}
  282. X
  283. X
  284. Xgsr_reset_terminal ()
  285. X/*-
  286. X   Do what has to be done to reset the terminal after we are all
  287. X   done plotting.  (Mostly just call (*t->reset).)
  288. X-*/
  289. X{
  290. X   struct termentry *t = >term_tbl[GTterm];
  291. X
  292. X   (*t->reset)();
  293. X#ifdef VMS
  294. X   vms_reset();
  295. X#endif
  296. X}
  297. X
  298. X
  299. Xgsr_draw_axis (xloc, yloc, visible)
  300. Xdouble xloc, yloc;
  301. Xint visible;
  302. X/*-
  303. X   Routine to draw axis lines (with linetype -1).  A horizontal line
  304. X   will be drawn at xloc and a vertical line at yloc.  Normal usage
  305. X   is for xloc and yloc to be 0.0  Note that the yloc value is also
  306. X   used as the line to draw impulses on for plotting IMPULSE style
  307. X   curves.  If ``visible'' is 0 then the lines won't be drawn, but
  308. X   GSRxaxis_y will be computed and saved for use with IMPULSE plots.
  309. X
  310. X   Parameters:
  311. X
  312. X         xloc:  Location (in user coordinates) of x axis line.
  313. X
  314. X         yloc:  Location (in user coordinates) of y axis line.
  315. X
  316. X      visible:  0 - neither axis is drawn, 
  317. X                1 - x axis only is drawn,
  318. X                2 - y axis only is drawn,
  319. X                3 - both axis are drawn.
  320. X
  321. X-*/
  322. X{
  323. X/* DRAW AXES */
  324. Xregister struct termentry *t = >term_tbl[GTterm];
  325. Xregister int xaxis_y, yaxis_x;
  326. X
  327. X/* Do we need to store linetype between each of these? */
  328. X    xaxis_y = gsr_map_y(xloc);
  329. X    yaxis_x = gsr_map_x(yloc); 
  330. X
  331. X    if (visible) 
  332. X        (*t->linetype)(-1);    /* axis line type */
  333. X
  334. X    if (xaxis_y < GSRybot)
  335. X        xaxis_y = GSRybot;                /* save for impulse plotting */
  336. X    else if (xaxis_y >= GSRytop)
  337. X        xaxis_y = GSRytop ;
  338. X    else if ((visible & 1) && !GSRlogy) {
  339. X        (*t->move)(GSRxleft,xaxis_y);
  340. X        (*t->vector)(GSRxright,xaxis_y);
  341. X    }
  342. X
  343. X    if ((visible & 2) && !GSRlogx && 
  344. X                yaxis_x >= GSRxleft && yaxis_x < GSRxright ) {
  345. X        (*t->move)(yaxis_x,GSRybot);
  346. X        (*t->vector)(yaxis_x,GSRytop);
  347. X    }
  348. X    GSRxaxis_y = xaxis_y;
  349. X}
  350. X
  351. X
  352. Xgsr_set_tic_format (xformat, yformat)
  353. Xchar *xformat, *yformat;
  354. X/*-
  355. X   Routine to change the x and y tic mark formats (GSRxformat and GSRyformat)
  356. X   the default for both is "%g".
  357. X
  358. X   Parameter:
  359. X
  360. X     xformat:  Pointer to new sprintf GSRxformat string;
  361. X
  362. X     yformat:  Pointer to new sprintf GSRyformat string;
  363. X-*/
  364. X{
  365. X   GSRxformat = xformat;
  366. X   GSRyformat = yformat;
  367. X}
  368. X
  369. X
  370. Xgsr_draw_tics (xtics, xgrid, xtic_in, ytics, ygrid, ytic_in)
  371. Xint xtics, xgrid, xtic_in, ytics, ygrid, ytic_in;
  372. X/*-
  373. X   Routine to draw and label the tic marks.
  374. X
  375. X   Parameters:
  376. X
  377. X        xtics:  If 1 draw x axis tics, if 0 don't.
  378. X
  379. X        xgrid:  If 1 draw an x grid, if 0 don't.
  380. X
  381. X      xtic_in:  If 1 draw the x tics inward, if 0 don't.
  382. X
  383. X        ytics:  If 1 draw y axis tics, if 0 don't.
  384. X
  385. X        ygrid:  If 1 draw a y grid, if 0 don't.
  386. X
  387. X      ytic_in:  If 1 draw the y tics inward, if 0 don't.
  388. X-*/
  389. X{
  390. X#define TIC_COMPUTED 1
  391. Xregister struct termentry *t = >term_tbl[GTterm];
  392. Xint type=TIC_COMPUTED;
  393. X
  394. X/* 
  395. X   This routine can be improved by allowing for TIC_SERIES and TIC_USER
  396. X   as is done in the main gnuplot package.
  397. X*/
  398. X   
  399. X/* DRAW TICS */
  400. X    (*t->linetype)(-2); /* border linetype */
  401. X
  402. X    /* label y axis tics */
  403. X     if (ytics) {
  404. X        switch (type) {
  405. X           case TIC_COMPUTED: {
  406. X               if (GSRymin < GSRymax)
  407. X                draw_ytics(GSRytic * floor(GSRymin/GSRytic),
  408. X                        GSRytic,
  409. X                        GSRytic * ceil(GSRymax/GSRytic), ygrid, ytic_in);
  410. X              else
  411. X                draw_ytics(GSRytic * floor(GSRymax/GSRytic),
  412. X                        GSRytic,
  413. X                        GSRytic * ceil(GSRymin/GSRytic), ygrid, ytic_in);
  414. X
  415. X              break;
  416. X           }
  417. X#ifdef NOTUSED_YET
  418. X           case TIC_SERIES: {
  419. X              draw_ytics(yticdef.def.series.start, 
  420. X                      yticdef.def.series.incr, 
  421. X                      yticdef.def.series.end, ygrid, ytic_in);
  422. X              break;
  423. X           }
  424. X           case TIC_USER: {
  425. X              draw_user_ytics(yticdef.def.user, ygrid, ytic_in);
  426. X              break;
  427. X           }
  428. X#endif
  429. X           default: {
  430. X              (*t->text)();
  431. X                (void) fflush(GSRoutfile);
  432. X              int_error("unknown tic type in yticdef in do_plot", NO_CARET);
  433. X              break;        /* NOTREACHED */
  434. X           }
  435. X        }
  436. X    }
  437. X
  438. X    /* label x axis tics */
  439. X     if (xtics) {
  440. X        switch (type) {
  441. X           case TIC_COMPUTED: {
  442. X               if (GSRxmin < GSRxmax)
  443. X                draw_xtics(GSRxtic * floor(GSRxmin/GSRxtic),
  444. X                        GSRxtic,
  445. X                        GSRxtic * ceil(GSRxmax/GSRxtic), xgrid, xtic_in);
  446. X              else
  447. X                draw_xtics(GSRxtic * floor(GSRxmax/GSRxtic),
  448. X                        GSRxtic,
  449. X                        GSRxtic * ceil(GSRxmin/GSRxtic), xgrid, xtic_in);
  450. X
  451. X              break;
  452. X           }
  453. X#ifdef NOTUSED_YET
  454. X           case TIC_SERIES: {
  455. X              draw_xtics(xticdef.def.series.start, 
  456. X                      xticdef.def.series.incr, 
  457. X                      xticdef.def.series.end, xgrid, xtic_in);
  458. X              break;
  459. X           }
  460. X           case TIC_USER: {
  461. X              draw_user_xtics(xticdef.def.user, xgrid, xtic_in);
  462. X              break;
  463. X           }
  464. X#endif
  465. X           default: {
  466. X              (*t->text)();
  467. X              (void) fflush(GSRoutfile);
  468. X              int_error("unknown tic type in xticdef in do_plot", NO_CARET);
  469. X              break;        /* NOTREACHED */
  470. X           }
  471. X        }
  472. X    }
  473. X}
  474. X
  475. X
  476. Xgsr_boundary ()
  477. X/*-
  478. X   Routine to draw the boundary (border around the plot area).
  479. X-*/
  480. X{
  481. X
  482. X/* DRAW PLOT BORDER */
  483. Xregister struct termentry *t = >term_tbl[GTterm];
  484. X    (*t->linetype)(-2); /* border linetype */
  485. X    (*t->move)(GSRxleft,GSRybot);    
  486. X    (*t->vector)(GSRxright,GSRybot);    
  487. X    (*t->vector)(GSRxright,GSRytop);    
  488. X    (*t->vector)(GSRxleft,GSRytop);    
  489. X    (*t->vector)(GSRxleft,GSRybot);
  490. X}
  491. X
  492. Xgsr_ylabel (ylabel)
  493. Xchar *ylabel;
  494. X/*-
  495. X   Routine to write a text lable for the y-axis.  Some terminal
  496. X   drivers will write this as vertically oriented text.  LaTeX
  497. X   will center the horizontal text on the left side of the plot.
  498. X
  499. X   Parameter:
  500. X
  501. X      ylabel:  Text string to place as the y axis label.
  502. X-*/
  503. X{
  504. X/* PLACE YLABEL */
  505. Xregister struct termentry *t = >term_tbl[GTterm];
  506. X    if (*ylabel != NULL) {
  507. X       if ((*t->text_angle)(1)) { 
  508. X          if ((*t->justify_text)(CENTRE)) { 
  509. X             (*t->put_text)((t->v_char),
  510. X                         (GSRytop+GSRybot)/2, ylabel);
  511. X          }
  512. X          else {
  513. X             (*t->put_text)((t->v_char),
  514. X                         (GSRytop+GSRybot)/2-(t->h_char)*strlen(ylabel)/2, 
  515. X                         ylabel);
  516. X          }
  517. X       }
  518. X       else {
  519. X          (void)(*t->justify_text)(LEFT);
  520. X          (*t->put_text)(0,GSRytop+(t->v_char), ylabel);
  521. X       }
  522. X       (void)(*t->text_angle)(0);
  523. X    }
  524. X}
  525. X
  526. X
  527. Xgsr_xlabel (xlabel)
  528. Xchar *xlabel;
  529. X/*-
  530. X   Routine to write a text label for the x-axis.  
  531. X
  532. X   Parameter:
  533. X
  534. X      xlabel:  Text string to place as the x axis label.
  535. X-*/
  536. X{
  537. X
  538. X/* PLACE XLABEL */
  539. Xregister struct termentry *t = >term_tbl[GTterm];
  540. X    if (*xlabel != NULL) {
  541. X       if ((*t->justify_text)(CENTRE)) 
  542. X        (*t->put_text)( (GSRxleft+GSRxright)/2,
  543. X                    GSRybot-2*(t->v_char), xlabel);
  544. X       else
  545. X        (*t->put_text)( (GSRxleft+GSRxright)/2 - strlen(xlabel)*(t->h_char)/2,
  546. X                    GSRybot-2*(t->v_char), xlabel);
  547. X    }
  548. X}
  549. X
  550. Xgsr_title (title)
  551. Xchar *title;
  552. X/*-
  553. X   Routine to write a title at the top of the plot.  
  554. X
  555. X   Parameter:
  556. X
  557. X       title:  Text string to place as the title for the plot.
  558. X-*/
  559. X{
  560. X/* PLACE TITLE */
  561. Xregister struct termentry *t = >term_tbl[GTterm];
  562. X    if (*title != NULL) {
  563. X       if ((*t->justify_text)(CENTRE)) 
  564. X        (*t->put_text)( (GSRxleft+GSRxright)/2, 
  565. X                    GSRytop+(t->v_char), title);
  566. X       else
  567. X        (*t->put_text)( (GSRxleft+GSRxright)/2 - strlen(title)*(t->h_char)/2,
  568. X                    GSRytop+(t->v_char), title);
  569. X    }
  570. X}
  571. X
  572. X
  573. Xgsr_label (x, y, text, justify, position)
  574. Xdouble x,y;
  575. Xchar *text;
  576. XBOOLEAN justify;
  577. Xint position;
  578. X/*-
  579. X    Routine to place a label (text string) at (x,y) where (x,y) is in user
  580. X    coordinates.
  581. X
  582. X    Parameters:
  583. X
  584. X             x: user coordinate x location for text string.
  585. X
  586. X             y: user coordinate y location for text string.
  587. X
  588. X          text: Text to plot at this location.
  589. X
  590. X       justify: Flag indicating if text is to be justified in place:
  591. X                0 - don't justify
  592. X                1 - justify (if terminal device can do so).
  593. X
  594. X      position: From gtplot.h, one of LEFT, CENTRE, RIGHT 
  595. X-*/
  596. X{
  597. X/* PLACE LABELS */
  598. Xdouble xtemp, ytemp;
  599. Xregister struct termentry *t = >term_tbl[GTterm];
  600. X    xtemp = LogScale(x, GSRlogx, "label", "x");
  601. X    ytemp = LogScale(y, GSRlogy, "label", "y");
  602. X    if ((*t->justify_text)(position)) {
  603. X        (*t->put_text)(gsr_map_x(xtemp),gsr_map_y(ytemp),text);
  604. X    }
  605. X    else {
  606. X        switch(position) {
  607. X            case  LEFT:
  608. X                (*t->put_text)(gsr_map_x(xtemp),gsr_map_y(ytemp), text);
  609. X            break;
  610. X            case CENTRE:
  611. X                (*t->put_text)(gsr_map_x(xtemp)-(t->h_char)*strlen(text)/2,
  612. X                    gsr_map_y(ytemp), text);
  613. X            break;
  614. X            case RIGHT:
  615. X                (*t->put_text)(gsr_map_x(xtemp)-(t->h_char)*strlen(text),
  616. X                        gsr_map_y(ytemp), text);
  617. X            break;
  618. X         }
  619. X     }
  620. X}
  621. X
  622. X
  623. Xgsr_arrow (start_x, start_y, end_x, end_y)
  624. Xdouble start_x, start_y, end_x, end_y;
  625. X/*-
  626. X    Draw an arrow from (start_x,start_y) to (end_x,end_y).
  627. X
  628. X    Parameters:
  629. X
  630. X       start_x:  starting x coordinate in user coordinates.
  631. X
  632. X       start_y:  starting y coordinate in user coordinates.
  633. X
  634. X         end_x:  ending x coordinate in user coordinates.
  635. X
  636. X         end_y:  ending y coordinate in user coordinates.
  637. X-*/
  638. X{
  639. X/* PLACE ARROWS */
  640. Xregister struct termentry *t = >term_tbl[GTterm];
  641. X       int sx = gsr_map_x(LogScale(start_x, GSRlogx, "arrow", "x"));
  642. X       int sy = gsr_map_y(LogScale(start_y, GSRlogy, "arrow", "y"));
  643. X       int ex = gsr_map_x(LogScale(end_x, GSRlogx, "arrow", "x"));
  644. X       int ey = gsr_map_y(LogScale(end_y, GSRlogy, "arrow", "y"));
  645. X
  646. X    (*t->linetype)(0);    /* arrow line type */
  647. X       
  648. X       (*t->arrow)(sx, sy, ex, ey);
  649. X}
  650. X
  651. X
  652. Xgsr_curve (style, points, npoints)
  653. Xint style, npoints;
  654. Xstruct coordinate *points;
  655. X/*-
  656. X   Routine to draw the curve located in the array points to the device.
  657. X
  658. X   Parameters:
  659. X
  660. X        style: One of IMPULSES, LINES, POINTS, LINESPOINTS, or DOTS from
  661. X               gtplot.h
  662. X
  663. X       points: An array of npoints coordinates, where struct coordinate
  664. X               is defined in gtplot.h.
  665. X
  666. X      npoints: Number of points to plot out of the points array.
  667. X-*/
  668. X{
  669. Xregister struct termentry *t = >term_tbl[GTterm];
  670. X/* DRAW CURVES */
  671. X        switch(style) {
  672. X            case IMPULSES: 
  673. X               plot_impulses(points, npoints, GSRxaxis_y);
  674. X           break;
  675. X            case LINES: 
  676. X               plot_lines(points, npoints);
  677. X            break;
  678. X            case POINTS: 
  679. X               plot_points(points, npoints);
  680. X               break;
  681. X            case LINESPOINTS: 
  682. X               /* put lines */
  683. X               plot_lines(points, npoints);
  684. X
  685. X               /* put points */
  686. X               plot_points(points, npoints);
  687. X            break;
  688. X            case DOTS: 
  689. X               plot_dots(points, npoints);
  690. X            break;
  691. X            default:
  692. X              (*t->text)();
  693. X              (void) fflush(GSRoutfile);
  694. X              int_error("unknown style in gsr_points", NO_CARET);
  695. X              break;        /* NOTREACHED */
  696. X        }
  697. X}
  698. X
  699. X
  700. Xgsr_text()
  701. X/*- 
  702. X   Routine to call the appropriate terminal _text() routine.  This works
  703. X   together with gsr_graphics() to go in and out of graphics mode: 
  704. X
  705. X      gsr_graphics(); ... plot routines ...  gsr_text();
  706. X
  707. X   On many terminal devices this must be called before any of the plot 
  708. X   will show up on the device.
  709. X-*/
  710. X{
  711. Xregister struct termentry *t = >term_tbl[GTterm];
  712. X
  713. X    (*t->text)();
  714. X    (void) fflush(GSRoutfile);
  715. X}
  716. X
  717. X
  718. Xgsr_line_point_type (line_type, point_type)
  719. X/*-
  720. X   Routine to select (ahead of gsr_curve()) the line_type or point_type
  721. X   that you wish to use.
  722. X
  723. X   Parameters:
  724. X
  725. X    line_type:  The desired line type (from -2 - 12), the exact range
  726. X                depends upon the term device in use.
  727. X
  728. X   point_type:  The desired point type (from -1 - 6) the exact range
  729. X                depends upon the term device in use.
  730. X-*/
  731. X{
  732. X   struct termentry *t = >term_tbl[GTterm];
  733. X
  734. X/* Record both requests. */
  735. X   GSRpoint_type = point_type;
  736. X   GSRline_type = line_type;
  737. X
  738. X/* Actually set the line_type request. */
  739. X   (*t->linetype)(line_type);
  740. X}
  741. X   
  742. X
  743. X#define OUTRANGE   0
  744. X#define INRANGE    1
  745. X#define UNDEFINED -1
  746. X
  747. X/* plot_impulses:
  748. X * Plot the curves in IMPULSES style
  749. X */
  750. Xstatic void
  751. Xplot_impulses(points, npoints, xaxis_y)
  752. X    struct coordinate *points;
  753. X    int xaxis_y;
  754. X{
  755. X    int i;
  756. X    int x,y;
  757. X    int type;
  758. X    struct termentry *t = >term_tbl[GTterm];
  759. X
  760. X    for (i = 0; i < npoints; i++) {
  761. X       type = inrange (points[i].x, GSRxmin, GSRxmax) &&
  762. X                                    inrange (points[i].y, GSRymin, GSRymax);
  763. X       switch (type) {
  764. X          case INRANGE: {
  765. X             x = gsr_map_x(points[i].x);
  766. X             y = gsr_map_y(points[i].y);
  767. X             break;
  768. X          }
  769. X          case OUTRANGE: {
  770. X             if (!inrange(points[i].x, GSRxmin,GSRxmax))
  771. X               continue;
  772. X             x = gsr_map_x(points[i].x);
  773. X             if ((GSRymin < GSRymax && points[i].y < GSRymin)
  774. X                || (GSRymax < GSRymin && points[i].y > GSRymin))
  775. X               y = gsr_map_y(GSRymin);
  776. X             if ((GSRymin < GSRymax && points[i].y > GSRymax)
  777. X                || (GSRymax<GSRymin && points[i].y < GSRymax))
  778. X               y = gsr_map_y(GSRymax);
  779. X             break;
  780. X          }
  781. X          default:        /* just a safety */
  782. X          case UNDEFINED: {
  783. X             continue;
  784. X          }
  785. X       }
  786. X                    
  787. X       (*t->move)(x,xaxis_y);
  788. X       (*t->vector)(x,y);
  789. X    }
  790. X
  791. X}
  792. X
  793. X/* plot_lines:
  794. X * Plot the curves in LINES style
  795. X */
  796. Xstatic void
  797. Xplot_lines(points, npoints)
  798. X    struct coordinate *points;
  799. X    int npoints;
  800. X{
  801. X    int i;                /* point index */
  802. X    int x,y;                /* point in terminal coordinates */
  803. X    int type;
  804. X    int clip_lines1 = 0,  /* Not used yet. */
  805. X        clip_lines2 = 0;
  806. X    struct termentry *t = >term_tbl[GTterm];
  807. X    enum coord_type prev = UNDEFINED; /* type of previous point */
  808. X    double ex, ey;            /* an edge point */
  809. X    double lx[2], ly[2];        /* two edge points */
  810. X
  811. X    for (i = 0; i < npoints; i++) {
  812. X       type = inrange (points[i].x, GSRxmin, GSRxmax) &&
  813. X                                    inrange (points[i].y, GSRymin, GSRymax);
  814. X       switch (type) {
  815. X          case INRANGE: {
  816. X             x = gsr_map_x(points[i].x);
  817. X             y = gsr_map_y(points[i].y);
  818. X
  819. X             if (prev == INRANGE) {
  820. X                (*t->vector)(x,y);
  821. X             } else if (prev == OUTRANGE) {
  822. X                /* from outrange to inrange */
  823. X                if (!clip_lines1) {
  824. X                    (*t->move)(x,y);
  825. X                } else {
  826. X                    edge_intersect(points, i, &ex, &ey);
  827. X                    (*t->move)(gsr_map_x(ex), gsr_map_y(ey));
  828. X                    (*t->vector)(x,y);
  829. X                }
  830. X             } else {        /* prev == UNDEFINED */
  831. X                (*t->move)(x,y);
  832. X                (*t->vector)(x,y);
  833. X             }
  834. X                    
  835. X             break;
  836. X          }
  837. X          case OUTRANGE: {
  838. X             if (prev == INRANGE) {
  839. X                /* from inrange to outrange */
  840. X                if (clip_lines1) {
  841. X                    edge_intersect(points, i, &ex, &ey);
  842. X                    (*t->vector)(gsr_map_x(ex), gsr_map_y(ey));
  843. X                }
  844. X             } else if (prev == OUTRANGE) {
  845. X                /* from outrange to outrange */
  846. X                if (clip_lines2) {
  847. X                    if (two_edge_intersect(points, i, lx, ly)) {
  848. X                       (*t->move)(gsr_map_x(lx[0]), gsr_map_y(ly[0]));
  849. X                       (*t->vector)(gsr_map_x(lx[1]), gsr_map_y(ly[1]));
  850. X                    }
  851. X                }
  852. X             }
  853. X             break;
  854. X          }
  855. X          default:        /* just a safety */
  856. X          case UNDEFINED: {
  857. X             break;
  858. X          }
  859. X       }
  860. X       prev = type;
  861. X    }
  862. X}
  863. X
  864. X/* plot_points:
  865. X * Plot the curves in POINTS style
  866. X */
  867. Xstatic void
  868. Xplot_points(points, npoints)
  869. X    struct coordinate *points;
  870. X    int npoints;
  871. X{
  872. X    int i;
  873. X    int x,y;
  874. X    int type;
  875. X    struct termentry *t = >term_tbl[GTterm];
  876. X
  877. X    for (i = 0; i < npoints; i++) {
  878. X       type = inrange (points[i].x, GSRxmin, GSRxmax) &&
  879. X                                    inrange (points[i].y, GSRymin, GSRymax);
  880. X       if (type == INRANGE) {
  881. X          x = gsr_map_x(points[i].x);
  882. X          y = gsr_map_y(points[i].y);
  883. X          /* do clipping (was ...if necessary...) */
  884. X          if (   x >= GSRxleft + t->h_tic  && y >= GSRybot + t->v_tic 
  885. X              && x <= GSRxright - t->h_tic && y <= GSRytop - t->v_tic)
  886. X            (*t->point)(x,y, GSRpoint_type);
  887. X       }
  888. X    }
  889. X}
  890. X
  891. X/* plot_dots:
  892. X * Plot the curves in DOTS style
  893. X */
  894. Xstatic void
  895. Xplot_dots(points, npoints)
  896. X    struct coordinate *points;
  897. X    int npoints;
  898. X{
  899. X    int i;
  900. X    int x,y;
  901. X    int type;
  902. X    struct termentry *t = >term_tbl[GTterm];
  903. X
  904. X    for (i = 0; i < npoints; i++) {
  905. X       type = inrange (points[i].x, GSRxmin, GSRxmax) &&
  906. X                                    inrange (points[i].y, GSRymin, GSRymax);
  907. X       if (type == INRANGE) {
  908. X          x = gsr_map_x(points[i].x);
  909. X          y = gsr_map_y(points[i].y);
  910. X          /* point type -1 is a dot */
  911. X          (*t->point)(x,y, -1);
  912. X       }
  913. X    }
  914. X}
  915. X
  916. X
  917. X/* single edge intersection algorithm */
  918. X/* Given two points, one inside and one outside the plot, return
  919. X * the point where an edge of the plot intersects the line segment defined 
  920. X * by the two points.
  921. X */
  922. Xstatic void
  923. Xedge_intersect(points, i, ex, ey)
  924. X    struct coordinate *points; /* the points array */
  925. X    int i;                /* line segment from point i-1 to point i */
  926. X    double *ex, *ey;        /* the point where it crosses an edge */
  927. X{
  928. X    /* global xmin, xmax, ymin, xmax */
  929. X    double ax = points[i-1].x;
  930. X    double ay = points[i-1].y;
  931. X    double bx = points[i].x;
  932. X    double by = points[i].y;
  933. X    double x, y;            /* possible intersection point */
  934. X
  935. X    if (by == ay) {
  936. X       /* horizontal line */
  937. X       /* assume inrange(by, GSRymin, GSRymax) */
  938. X       *ey = by;        /* == ay */
  939. X
  940. X       if (inrange(GSRxmax, ax, bx))
  941. X        *ex = GSRxmax;
  942. X       else if (inrange(GSRxmin, ax, bx))
  943. X        *ex = GSRxmin;
  944. X       else {
  945. X        (*GTterm_tbl[GTterm].text)();
  946. X        (void) fflush(GSRoutfile);
  947. X        int_error("error in edge_intersect", NO_CARET);
  948. X       }
  949. X       return;
  950. X    } else if (bx == ax) {
  951. X       /* vertical line */
  952. X       /* assume inrange(bx, GSRxmin, GSRxmax) */
  953. X       *ex = bx;        /* == ax */
  954. X
  955. X       if (inrange(GSRymax, ay, by))
  956. X        *ey = GSRymax;
  957. X       else if (inrange(GSRymin, ay, by))
  958. X        *ey = GSRymin;
  959. X       else {
  960. X        (*GTterm_tbl[GTterm].text)();
  961. X        (void) fflush(GSRoutfile);
  962. X        int_error("error in edge_intersect", NO_CARET);
  963. X       }
  964. X       return;
  965. X    }
  966. X
  967. X    /* slanted line of some kind */
  968. X
  969. X    /* does it intersect ymin edge */
  970. X    if (inrange(GSRymin, ay, by) && GSRymin != ay && GSRymin != by) {
  971. X       x = ax + (GSRymin-ay) * ((bx-ax) / (by-ay));
  972. X       if (inrange(x, GSRxmin, GSRxmax)) {
  973. X          *ex = x;
  974. X          *ey = GSRymin;
  975. X          return;            /* yes */
  976. X       }
  977. X    }
  978. X    
  979. X    /* does it intersect ymax edge */
  980. X    if (inrange(GSRymax, ay, by) && GSRymax != ay && GSRymax != by) {
  981. X       x = ax + (GSRymax-ay) * ((bx-ax) / (by-ay));
  982. X       if (inrange(x, GSRxmin, GSRxmax)) {
  983. X          *ex = x;
  984. X          *ey = GSRymax;
  985. X          return;            /* yes */
  986. X       }
  987. X    }
  988. X
  989. X    /* does it intersect xmin edge */
  990. X    if (inrange(GSRxmin, ax, bx) && GSRxmin != ax && GSRxmin != bx) {
  991. X       y = ay + (GSRxmin-ax) * ((by-ay) / (bx-ax));
  992. X       if (inrange(y, GSRymin, GSRymax)) {
  993. X          *ex = GSRxmin;
  994. X          *ey = y;
  995. X          return;
  996. X       }
  997. X    }
  998. X
  999. X    /* does it intersect xmax edge */
  1000. X    if (inrange(GSRxmax, ax, bx) && GSRxmax != ax && GSRxmax != bx) {
  1001. X       y = ay + (GSRxmax-ax) * ((by-ay) / (bx-ax));
  1002. X       if (inrange(y, GSRymin, GSRymax)) {
  1003. X          *ex = GSRxmax;
  1004. X          *ey = y;
  1005. X          return;
  1006. X       }
  1007. X    }
  1008. X
  1009. X    /* It is possible for one or two of the [ab][xy] values to be -VERYLARGE.
  1010. X    * If ax=bx=-VERYLARGE or ay=by=-VERYLARGE we have already returned 
  1011. X    * FALSE above. Otherwise we fall through all the tests above. 
  1012. X    * If two are -VERYLARGE, it is ax=ay=-VERYLARGE or bx=by=-VERYLARGE 
  1013. X    * since either a or b must be INRANGE. 
  1014. X    * Note that for ax=ay=-VERYLARGE or bx=by=-VERYLARGE we can do nothing.
  1015. X    * Handle them carefully here. As yet we have no way for them to be 
  1016. X    * +VERYLARGE.
  1017. X    */
  1018. X    if (ax == -VERYLARGE) {
  1019. X       if (ay != -VERYLARGE) {
  1020. X          *ex = min(GSRxmin, GSRxmax);
  1021. X          *ey = by;
  1022. X          return;
  1023. X       }
  1024. X    } else if (bx == -VERYLARGE) {
  1025. X       if (by != -VERYLARGE) {
  1026. X          *ex = min(GSRxmin, GSRxmax);
  1027. X          *ey = ay;
  1028. X          return;
  1029. X       }
  1030. X    } else if (ay == -VERYLARGE) {
  1031. X       /* note we know ax != -VERYLARGE */
  1032. X       *ex = bx;
  1033. X       *ey = min(GSRymin, GSRymax);
  1034. X       return;
  1035. X    } else if (by == -VERYLARGE) {
  1036. X       /* note we know bx != -VERYLARGE */
  1037. X       *ex = ax;
  1038. X       *ey = min(GSRymin, GSRymax);
  1039. X       return;
  1040. X    }
  1041. X
  1042. X    /* If we reach here, then either one point is (-VERYLARGE,-VERYLARGE), 
  1043. X    * or the inrange point is on the edge, and
  1044. X     * the line segment from the outrange point does not cross any 
  1045. X    * other edges to get there. In either case, we return the inrange 
  1046. X    * point as the 'edge' intersection point. This will basically draw
  1047. X    * line.
  1048. X    */
  1049. X/* Had to change this--just guessing this is right.  JDC */
  1050. X    if (points[i].x != -VERYLARGE) {
  1051. X       *ex = bx; 
  1052. X       *ey = by;
  1053. X    } else {
  1054. X       *ex = ax; 
  1055. X       *ey = ay;
  1056. X    }
  1057. X    return;
  1058. X}
  1059. X
  1060. X/* double edge intersection algorithm */
  1061. X/* Given two points, both outside the plot, return
  1062. X * the points where an edge of the plot intersects the line segment defined 
  1063. X * by the two points. There may be zero, one, two, or an infinite number
  1064. X * of intersection points. (One means an intersection at a corner, infinite
  1065. X * means overlaying the edge itself). We return FALSE when there is nothing
  1066. X * to draw (zero intersections), and TRUE when there is something to 
  1067. X * draw (the one-point case is a degenerate of the two-point case and we do 
  1068. X * not distinguish it - we draw it anyway).
  1069. X */
  1070. Xstatic BOOLEAN                /* any intersection? */
  1071. Xtwo_edge_intersect(points, i, lx, ly)
  1072. X    struct coordinate *points; /* the points array */
  1073. X    int i;                /* line segment from point i-1 to point i */
  1074. X    double *lx, *ly;        /* lx[2], ly[2]: points where it crosses edges */
  1075. X{
  1076. X    /* global xmin, xmax, ymin, xmax */
  1077. X    double ax = points[i-1].x;
  1078. X    double ay = points[i-1].y;
  1079. X    double bx = points[i].x;
  1080. X    double by = points[i].y;
  1081. X    double x, y;            /* possible intersection point */
  1082. X    BOOLEAN intersect = FALSE;
  1083. X
  1084. X    if (by == ay) {
  1085. X       /* horizontal line */
  1086. X       /* y coord must be in range, and line must span both xmin and xmax */
  1087. X       /* note that spanning GSRxmin implies spanning GSRxmax */
  1088. X       if (inrange(by, GSRymin, GSRymax) && inrange(GSRxmin, ax, bx)) {
  1089. X          *lx++ = GSRxmin;
  1090. X          *ly++ = by;
  1091. X          *lx++ = GSRxmax;
  1092. X          *ly++ = by;
  1093. X          return(TRUE);
  1094. X       } else
  1095. X        return(FALSE);
  1096. X    } else if (bx == ax) {
  1097. X       /* vertical line */
  1098. X       /* x coord must be in range, and line must span both GSRymin and GSRymax */
  1099. X       /* note that spanning GSRymin implies spanning GSRymax */
  1100. X       if (inrange(bx, GSRxmin, GSRxmax) && inrange(GSRymin, ay, by)) {
  1101. X          *lx++ = bx;
  1102. X          *ly++ = GSRymin;
  1103. X          *lx++ = bx;
  1104. X          *ly++ = GSRymax;
  1105. X          return(TRUE);
  1106. X       } else
  1107. X        return(FALSE);
  1108. X    }
  1109. X
  1110. X    /* slanted line of some kind */
  1111. X    /* there can be only zero or two intersections below */
  1112. X
  1113. X    /* does it intersect GSRymin edge */
  1114. X    if (inrange(GSRymin, ay, by)) {
  1115. X       x = ax + (GSRymin-ay) * ((bx-ax) / (by-ay));
  1116. X       if (inrange(x, GSRxmin, GSRxmax)) {
  1117. X          *lx++ = x;
  1118. X          *ly++ = GSRymin;
  1119. X          intersect = TRUE;
  1120. X       }
  1121. X    }
  1122. X    
  1123. X    /* does it intersect GSRymax edge */
  1124. X    if (inrange(GSRymax, ay, by)) {
  1125. X       x = ax + (GSRymax-ay) * ((bx-ax) / (by-ay));
  1126. X       if (inrange(x, GSRxmin, GSRxmax)) {
  1127. X          *lx++ = x;
  1128. X          *ly++ = GSRymax;
  1129. X          intersect = TRUE;
  1130. X       }
  1131. X    }
  1132. X
  1133. X    /* does it intersect GSRxmin edge */
  1134. X    if (inrange(GSRxmin, ax, bx)) {
  1135. X       y = ay + (GSRxmin-ax) * ((by-ay) / (bx-ax));
  1136. X       if (inrange(y, GSRymin, GSRymax)) {
  1137. X          *lx++ = GSRxmin;
  1138. X          *ly++ = y;
  1139. X          intersect = TRUE;
  1140. X       }
  1141. X    }
  1142. X
  1143. X    /* does it intersect GSRxmax edge */
  1144. X    if (inrange(GSRxmax, ax, bx)) {
  1145. X       y = ay + (GSRxmax-ax) * ((by-ay) / (bx-ax));
  1146. X       if (inrange(y, GSRymin, GSRymax)) {
  1147. X          *lx++ = GSRxmax;
  1148. X          *ly++ = y;
  1149. X          intersect = TRUE;
  1150. X       }
  1151. X    }
  1152. X
  1153. X    if (intersect)
  1154. X     return(TRUE);
  1155. X
  1156. X    /* It is possible for one or more of the [ab][xy] values to be -VERYLARGE.
  1157. X    * If ax=bx=-VERYLARGE or ay=by=-VERYLARGE we have already returned
  1158. X    * FALSE above.
  1159. X    * Note that for ax=ay=-VERYLARGE or bx=by=-VERYLARGE we can do nothing.
  1160. X    * Otherwise we fall through all the tests above. 
  1161. X    * Handle them carefully here. As yet we have no way for them to be +VERYLARGE.
  1162. X    */
  1163. X    if (ax == -VERYLARGE) {
  1164. X       if (ay != -VERYLARGE
  1165. X          && inrange(by, GSRymin, GSRymax) && inrange(GSRxmax, ax, bx)) {
  1166. X          *lx++ = GSRxmin;
  1167. X          *ly = by;
  1168. X          *lx++ = GSRxmax;
  1169. X          *ly = by;
  1170. X          intersect = TRUE;
  1171. X       }
  1172. X    } else if (bx == -VERYLARGE) {
  1173. X       if (by != -VERYLARGE
  1174. X          && inrange(ay, GSRymin, GSRymax) && inrange(GSRxmax, ax, bx)) {
  1175. X          *lx++ = GSRxmin;
  1176. X          *ly = ay;
  1177. X          *lx++ = GSRxmax;
  1178. X          *ly = ay;
  1179. X          intersect = TRUE;
  1180. X       }
  1181. X    } else if (ay == -VERYLARGE) {
  1182. X       /* note we know ax != -VERYLARGE */
  1183. X       if (inrange(bx, GSRxmin, GSRxmax) && inrange(GSRymax, ay, by)) {
  1184. X          *lx++ = bx;
  1185. X          *ly = GSRymin;
  1186. X          *lx++ = bx;
  1187. X          *ly = GSRymax;
  1188. X          intersect = TRUE;
  1189. X       }
  1190. X    } else if (by == -VERYLARGE) {
  1191. X       /* note we know bx != -VERYLARGE */
  1192. X       if (inrange(ax, GSRxmin, GSRxmax) && inrange(GSRymax, ay, by)) {
  1193. X          *lx++ = ax;
  1194. X          *ly = GSRymin;
  1195. X          *lx++ = ax;
  1196. X          *ly = GSRymax;
  1197. X          intersect = TRUE;
  1198. X       }
  1199. X    }
  1200. X
  1201. X    return(intersect);
  1202. X}
  1203. X
  1204. X/* DRAW_YTICS: draw a regular tic series, y axis */
  1205. Xstatic draw_ytics(start, incr, end, ygrid, ytic_in)
  1206. Xdouble start, incr, end; /* tic series definition */
  1207. Xint ygrid, ytic_in;
  1208. X        /* assume start < end, incr > 0 */
  1209. X{
  1210. X    double ticplace;
  1211. X    int ltic;            /* for mini log tics */
  1212. X    double lticplace;    /* for mini log tics */
  1213. X    double ticmin, ticmax;    /* for checking if tic is almost inrange */
  1214. X
  1215. X    if (end == VERYLARGE)            /* for user-def series */
  1216. X        end = max(GSRymin,GSRymax);
  1217. X
  1218. X    /* limit to right side of plot */
  1219. X    end = min(end, max(GSRymin,GSRymax));
  1220. X
  1221. X    /* to allow for rounding errors */
  1222. X    ticmin = min(GSRymin,GSRymax) - SIGNIF*incr;
  1223. X    ticmax = max(GSRymin,GSRymax) + SIGNIF*incr;
  1224. X    end = end + SIGNIF*incr; 
  1225. X
  1226. X    for (ticplace = start; ticplace <= end; ticplace +=incr) {
  1227. X        if ( inrange(ticplace,ticmin,ticmax) )
  1228. X            ytick(ticplace, GSRyformat, incr, 1.0, ygrid, ytic_in);
  1229. X        if (GSRlogy && incr == 1.0) {
  1230. X            /* add mini-ticks to log scale ticmarks */
  1231. X            for (ltic = 2; ltic <= 9; ltic++) {
  1232. X                lticplace = ticplace+log10((double)ltic);
  1233. X                if ( inrange(lticplace,ticmin,ticmax) )
  1234. X                    ytick(lticplace, (char *)NULL, incr, 0.5, ygrid, ytic_in);
  1235. X            }
  1236. X        }
  1237. X    }
  1238. X}
  1239. X
  1240. X
  1241. X/* DRAW_XTICS: draw a regular tic series, x axis */
  1242. Xstatic draw_xtics(start, incr, end, xgrid, xtic_in)
  1243. Xdouble start, incr, end; /* tic series definition */
  1244. Xint xgrid, xtic_in;
  1245. X        /* assume start < end, incr > 0 */
  1246. X{
  1247. X    double ticplace;
  1248. X    int ltic;            /* for mini log tics */
  1249. X    double lticplace;    /* for mini log tics */
  1250. X    double ticmin, ticmax;    /* for checking if tic is almost inrange */
  1251. X
  1252. X    if (end == VERYLARGE)            /* for user-def series */
  1253. X        end = max(GSRxmin,GSRxmax);
  1254. X
  1255. X    /* limit to right side of plot */
  1256. X    end = min(end, max(GSRxmin,GSRxmax));
  1257. X
  1258. X    /* to allow for rounding errors */
  1259. X    ticmin = min(GSRxmin,GSRxmax) - SIGNIF*incr;
  1260. X    ticmax = max(GSRxmin,GSRxmax) + SIGNIF*incr;
  1261. X    end = end + SIGNIF*incr; 
  1262. X
  1263. X    for (ticplace = start; ticplace <= end; ticplace +=incr) {
  1264. X        if ( inrange(ticplace,ticmin,ticmax) )
  1265. X            xtick(ticplace, GSRxformat, incr, 1.0, xgrid, xtic_in);
  1266. X        if (GSRlogx && incr == 1.0) {
  1267. X            /* add mini-ticks to log scale ticmarks */
  1268. X            for (ltic = 2; ltic <= 9; ltic++) {
  1269. X                lticplace = ticplace+log10((double)ltic);
  1270. X                if ( inrange(lticplace,ticmin,ticmax) )
  1271. X                    xtick(lticplace, (char *)NULL, incr, 0.5, xgrid, xtic_in);
  1272. X            }
  1273. X        }
  1274. X    }
  1275. X}
  1276. X
  1277. X#ifdef NOTUSED_YET
  1278. X/* DRAW_USER_YTICS: draw a user tic series, y axis */
  1279. Xstatic draw_user_ytics(list, ygrid, ytic_in)
  1280. Xstruct ticmark *list;    /* list of tic marks */
  1281. Xint ygrid, ytic_in;
  1282. X{
  1283. X    double ticplace;
  1284. X    double incr = (GSRymax - GSRymin) / 10;
  1285. X    /* global GSRxmin, GSRxmax, xscale, GSRymin, GSRymax, yscale */
  1286. X
  1287. X    while (list != NULL) {
  1288. X       ticplace = list->position;
  1289. X       if ( inrange(ticplace, GSRymin, GSRymax)         /* in range */
  1290. X          || NearlyEqual(ticplace, GSRymin, incr)    /* == GSRymin */
  1291. X          || NearlyEqual(ticplace, GSRymax, incr))    /* == GSRymax */
  1292. X        ytick(ticplace, list->label, incr, 1.0, ygrid, ytic_in);
  1293. X
  1294. X       list = list->next;
  1295. X    }
  1296. X}
  1297. X#endif
  1298. X
  1299. X#ifdef NOTUSED_YET
  1300. X/* DRAW_USER_XTICS: draw a user tic series, x axis */
  1301. Xstatic draw_user_xtics(list, xgrid, xtic_in)
  1302. Xstruct ticmark *list;    /* list of tic marks */
  1303. Xint xgrid, xtic_in;
  1304. X{
  1305. X    double ticplace;
  1306. X    double incr = (GSRxmax - GSRxmin) / 10;
  1307. X    /* global GSRxmin, GSRxmax, xscale, GSRymin, GSRymax, yscale */
  1308. X
  1309. X    while (list != NULL) {
  1310. X       ticplace = list->position;
  1311. X       if ( inrange(ticplace, GSRxmin, GSRxmax)         /* in range */
  1312. X          || NearlyEqual(ticplace, GSRxmin, incr)    /* == GSRxmin */
  1313. X          || NearlyEqual(ticplace, GSRxmax, incr))    /* == GSRxmax */
  1314. X        xtick(ticplace, list->label, incr, 1.0, xgrid, xtic_in);
  1315. X
  1316. X       list = list->next;
  1317. X    }
  1318. X}
  1319. X#endif
  1320. X
  1321. X/* draw and label a y-axis ticmark */
  1322. Xstatic ytick(place, text, spacing, ticscale, ygrid, ytic_in)
  1323. Xdouble place;                   /* where on axis to put it */
  1324. Xchar *text;                     /* optional text label */
  1325. Xdouble spacing;         /* something to use with checkzero */
  1326. Xfloat ticscale;         /* scale factor for tic mark (0..1] */
  1327. Xint ygrid, ytic_in;
  1328. X{
  1329. X    register struct termentry *t = >term_tbl[GTterm];
  1330. X    char ticlabel[101];
  1331. X    int ticsize = (int)((t->h_tic) * ticscale);
  1332. X
  1333. X    place = CheckZero(place,spacing); /* to fix rounding error near zero */
  1334. X    if (ygrid) {
  1335. X           (*t->linetype)(-1);  /* axis line type */
  1336. X           (*t->move)(GSRxleft, gsr_map_y(place));
  1337. X           (*t->vector)(GSRxright, gsr_map_y(place));
  1338. X           (*t->linetype)(-2); /* border linetype */
  1339. X    }
  1340. X    if (ytic_in) {
  1341. X           (*t->move)(GSRxleft, gsr_map_y(place));
  1342. X           (*t->vector)(GSRxleft + ticsize, gsr_map_y(place));
  1343. X           (*t->move)(GSRxright, gsr_map_y(place));
  1344. X           (*t->vector)(GSRxright - ticsize, gsr_map_y(place));
  1345. X    } else {
  1346. X           (*t->move)(GSRxleft, gsr_map_y(place));
  1347. X           (*t->vector)(GSRxleft - ticsize, gsr_map_y(place));
  1348. X    }
  1349. X
  1350. X    /* label the ticmark */
  1351. X    if (text) {
  1352. X        (void) sprintf(ticlabel, text, CheckLog(GSRlogy, place));
  1353. X        if ((*t->justify_text)(RIGHT)) {
  1354. X           (*t->put_text)(GSRxleft-(t->h_char),
  1355. X                       gsr_map_y(place), ticlabel);
  1356. X        } else {
  1357. X           (*t->put_text)(GSRxleft-(t->h_char)*(strlen(ticlabel)+1),
  1358. X                       gsr_map_y(place), ticlabel);
  1359. X        }
  1360. X    }
  1361. X}
  1362. X
  1363. X/* draw and label an x-axis ticmark */
  1364. Xstatic xtick(place, text, spacing, ticscale, xgrid, xtic_in)
  1365. Xdouble place;                   /* where on axis to put it */
  1366. Xchar *text;                     /* optional text label */
  1367. Xdouble spacing;         /* something to use with checkzero */
  1368. Xfloat ticscale;         /* scale factor for tic mark (0..1] */
  1369. Xint xgrid, xtic_in;
  1370. X{
  1371. X    register struct termentry *t = >term_tbl[GTterm];
  1372. X    char ticlabel[101];
  1373. X    int ticsize = (int)((t->v_tic) * ticscale);
  1374. X
  1375. X    place = CheckZero(place,spacing); /* to fix rounding error near zero */
  1376. X    if (xgrid) {
  1377. X           (*t->linetype)(-1);  /* axis line type */
  1378. X           (*t->move)(gsr_map_x(place), GSRybot);
  1379. X           (*t->vector)(gsr_map_x(place), GSRytop);
  1380. X           (*t->linetype)(-2); /* border linetype */
  1381. X    }
  1382. X    if (xtic_in) {
  1383. X           (*t->move)(gsr_map_x(place), GSRybot);
  1384. X           (*t->vector)(gsr_map_x(place), GSRybot + ticsize);
  1385. X           (*t->move)(gsr_map_x(place), GSRytop);
  1386. X           (*t->vector)(gsr_map_x(place), GSRytop - ticsize);
  1387. X    } else {
  1388. X           (*t->move)(gsr_map_x(place), GSRybot);
  1389. X           (*t->vector)(gsr_map_x(place), GSRybot - ticsize);
  1390. X    }
  1391. X
  1392. X    /* label the ticmark */
  1393. X    if (text) {
  1394. X       (void) sprintf(ticlabel, text, CheckLog(GSRlogx, place));
  1395. X       if ((*t->justify_text)(CENTRE)) {
  1396. X          (*t->put_text)(gsr_map_x(place),
  1397. X                      GSRybot-(t->v_char), ticlabel);
  1398. X       } else {
  1399. X          (*t->put_text)(gsr_map_x(place)-(t->h_char)*strlen(ticlabel)/2,
  1400. X                      GSRybot-(t->v_char), ticlabel);
  1401. X       }
  1402. X    }
  1403. X}
  1404. X
  1405. Xstatic int_error(str,t_num)
  1406. Xchar str[];
  1407. Xint t_num;
  1408. X/*
  1409. X   Routine to print an error and die.  This is modified from the more
  1410. X   complex gnuplot version which longjumps back to the gnuplot prompt.
  1411. X   Note: NO_CARET is kept in some of the code above just to make these
  1412. X   routines look more like the originals.  It isn't used at all here, 
  1413. X   however.
  1414. X*/
  1415. X{
  1416. X/* t_num is the token number, we don't have tokens... */
  1417. X     fprintf(stderr,"%s\n\n", str);
  1418. X
  1419. X#ifdef MAYBE_LATER
  1420. X    longjmp(env, TRUE);    /* bail out to command line */
  1421. X#else
  1422. X    exit(1);
  1423. X#endif
  1424. X}
  1425. END_OF_FILE
  1426. if test 37808 -ne `wc -c <'gsr.c'`; then
  1427.     echo shar: \"'gsr.c'\" unpacked with wrong size!
  1428. fi
  1429. # end of 'gsr.c'
  1430. fi
  1431. echo shar: End of archive 4 \(of 5\).
  1432. cp /dev/null ark4isdone
  1433. MISSING=""
  1434. for I in 1 2 3 4 5 ; do
  1435.     if test ! -f ark${I}isdone ; then
  1436.     MISSING="${MISSING} ${I}"
  1437.     fi
  1438. done
  1439. if test "${MISSING}" = "" ; then
  1440.     echo You have unpacked all 5 archives.
  1441.     rm -f ark[1-9]isdone
  1442. else
  1443.     echo You still need to unpack the following archives:
  1444.     echo "        " ${MISSING}
  1445. fi
  1446. ##  End of shell archive.
  1447. exit 0
  1448.  
  1449.